package essential;
import javax.vecmath.*;

public class Camera {
	double wfov;
	double hfov;
	double aspectRatio;
	Vector3d origin;

	Vector3d forward;
	Vector3d up;
	Vector3d right;
	
	public Vector3d getOrigin() {
		return origin;
	}

	public Camera copy() {
		Camera c = new Camera();
		c.wfov = wfov;
		c.hfov = hfov;
		c.aspectRatio = aspectRatio;
		c.origin = new Vector3d(origin);
		c.forward = new Vector3d(forward);
		c.up = new Vector3d(up);
		c.right = new Vector3d(right);

		return c;
	}
	
	public Camera() {}
	
	//Well, no rotation for this camera, will be fixed later
	public Camera(Vector3d target, Vector3d origin, Vector3d up, double fov, double aspectRatio) {
		this.forward = new Vector3d(target);
		this.forward.sub(origin);
		this.forward.normalize();
		
		this.up = new Vector3d();
		this.right = new Vector3d();
		this.origin = origin;
		this.aspectRatio = aspectRatio;

		this.wfov = Math.toRadians(fov);
		//this.hfov = fov / aspectRatio;
		this.hfov = 2 * Math.atan(Math.tan(wfov/2) / aspectRatio);
		//Vector3d worldUp = new Vector3d(0, 1, 0);
		right.cross(forward, up);
		this.up.cross(forward, right);

		forward.normalize();
		this.up.normalize();
		right.normalize();
	}

	public Vector3d leftUpCorner() {
		Vector3d corner = new Vector3d(forward);
		Vector3d offsetw = new Vector3d(right);
		Vector3d offseth = new Vector3d(up);

		offsetw.scale(Math.tan(wfov/2));
		offseth.scale(Math.tan(hfov/2));
		offsetw.negate();
		
		corner.add(offsetw);
		corner.add(offseth);
		return corner;
	}
	
	public Vector3d rightUpCorner() {
		Vector3d corner = new Vector3d(forward);
		Vector3d offsetw = new Vector3d(right);
		Vector3d offseth = new Vector3d(up);

		offsetw.scale(Math.tan(wfov/2));
		offseth.scale(Math.tan(hfov/2));

		corner.add(offsetw);
		corner.add(offseth);
		return corner;
	}

	public Vector3d leftDownCorner() {
		Vector3d corner = new Vector3d(forward);
		Vector3d offsetw = new Vector3d(right);
		Vector3d offseth = new Vector3d(up);

		offsetw.scale(Math.tan(wfov/2));
		offseth.scale(Math.tan(hfov/2));
		offsetw.negate();
		offseth.negate();

		corner.add(offsetw);
		corner.add(offseth);
		return corner;
	}
	
	public Vector3d rightDownCorner() {
		Vector3d corner = new Vector3d(forward);
		Vector3d offsetw = new Vector3d(right);
		Vector3d offseth = new Vector3d(up);
		
		offsetw.scale(Math.tan(wfov/2));
		offseth.scale(Math.tan(hfov/2));
		offseth.negate();

		corner.add(offsetw);
		corner.add(offseth);
		return corner;
	}
}
